use chrono::{DateTime, Local, TimeZone, Utc};
use serde::{Deserialize, Serialize, de, ser};

// 自定义序列化函数
pub fn serialize<S>(dt: &DateTime<Local>, serializer: S) -> Result<S::Ok, S::Error>
where
    S: ser::Serializer,
{
    const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
    serializer.serialize_str(&dt.format(FORMAT).to_string())
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Local>, D::Error>
where
    D: de::Deserializer<'de>,
{
    use chrono::{DateTime, Local, NaiveDateTime};

    let s = String::deserialize(deserializer)?;

    // 尝试解析为带有时区的字符串
    if let Ok(dt) =
        DateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S%.f %z").map(|dt| dt.with_timezone(&Local))
    {
        return Ok(dt);
    }

    if let Ok(dt) =
        DateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S %z").map(|dt| dt.with_timezone(&Local))
    {
        return Ok(dt);
    }

    // 尝试解析为无时区的字符串，并假设为本地时间
    if let Ok(dt) = NaiveDateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S%.f") {
        return match Local.from_local_datetime(&dt).single() {
            Some(dt) => Ok(dt),
            None => Err(de::Error::custom(format!("Ambiguous time: {s}"))),
        };
    }

    if let Ok(dt) = NaiveDateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S") {
        return match Local.from_local_datetime(&dt).single() {
            Some(dt) => Ok(dt),
            None => Err(de::Error::custom(format!("Ambiguous time: {s}"))),
        };
    }

    Err(de::Error::custom(format!(
        "Failed to parse '{s}' as local datetime"
    )))
}

// 自定义序列化函数
pub fn serialize_utc<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
    S: ser::Serializer,
{
    const FORMAT: &str = "%Y-%m-%d %H:%M:%S";
    serializer.serialize_str(&dt.format(FORMAT).to_string())
}

pub fn deserialize_utc<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
    D: de::Deserializer<'de>,
{
    use chrono::{DateTime, NaiveDateTime, Utc};

    let s = String::deserialize(deserializer)?;

    // 尝试解析为带有时区的字符串
    if let Ok(dt) =
        DateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S%.f %z").map(|dt| dt.with_timezone(&Utc))
    {
        return Ok(dt);
    }

    if let Ok(dt) =
        DateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S %z").map(|dt| dt.with_timezone(&Utc))
    {
        return Ok(dt);
    }

    // 尝试解析为无时区的字符串，并假设为本地时间
    if let Ok(dt) = NaiveDateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S%.f") {
        return match Utc.from_local_datetime(&dt).single() {
            Some(dt) => Ok(dt),
            None => Err(de::Error::custom(format!("Ambiguous time: {s}"))),
        };
    }

    if let Ok(dt) = NaiveDateTime::parse_from_str(&s, "%Y-%m-%d %H:%M:%S") {
        return match Utc.from_local_datetime(&dt).single() {
            Some(dt) => Ok(dt),
            None => Err(de::Error::custom(format!("Ambiguous time: {s}"))),
        };
    }

    Err(de::Error::custom(format!(
        "Failed to parse '{s}' as local datetime"
    )))
}

#[derive(Debug)]
pub enum SortDirection {
    Ascending,
    Descending,
}

// 排序字段结构
#[derive(Debug)]
pub struct SortingField {
    pub name: String,
    pub direction: SortDirection,
}

#[derive(Debug, Serialize, Default)]
pub struct PaginatedResponse<T> {
    pub items: Vec<T>,
    pub current_page: i32,
    pub per_page: i32,
    pub total_items: i64,
    pub total_pages: i32,
}

// 解析排序字符串
pub fn parse_sort_fields(sort_str: Option<&str>) -> Vec<SortingField> {
    // 安全字段白名单
    const SAFE_FIELDS: &[&str] = &["id", "name", "created_at"];

    let mut fields = vec![];

    if let Some(sort_str) = sort_str {
        for field in sort_str.split(',') {
            let (name, direction) = match field.strip_prefix('-') {
                Some(n) => (n, SortDirection::Descending),
                None => (field, SortDirection::Ascending),
            };

            // 使用白名单验证字段名
            if SAFE_FIELDS.contains(&name) {
                fields.push(SortingField {
                    name: name.to_string(),
                    direction,
                });
            }
        }
    }

    // 确保至少有一个排序字段
    if fields.is_empty() {
        fields.push(SortingField {
            name: "id".to_string(),
            direction: SortDirection::Ascending,
        });
    }

    fields
}
